﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Practices.Prism.Logging;

namespace Infrastructure
{
    public abstract class BasePluginLoader
    {
        public virtual IEnumerable<T> LoadPlugin<T>(string pluginDirectoryName, ILoggerFacade logger) where T:class 
        {
            List<T> result = new List<T>();
            try
            {
                string tyString = typeof (T).Name.ToString(CultureInfo.InvariantCulture); 
                logger.Log(String.Format("Locating plugins of type {0} in directory {1}", tyString, pluginDirectoryName), Category.Info, Priority.Low);
                DirectoryInfo info = new DirectoryInfo(pluginDirectoryName);
                foreach (FileInfo fi in info.GetFiles("*.dll", SearchOption.AllDirectories))
                {
                    try
                    {
                        Assembly a = Assembly.LoadFile(fi.FullName);
                        foreach (Type t in a.GetExportedTypes())
                        {
                            result.AddRange(from i in t.GetInterfaces() where i.Name == tyString select Activator.CreateInstance(t) as T);
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Log("Unable to load assembly  " + fi.FullName + " Message: " + ex.Message, Category.Exception, Priority.High);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Log("LoadPlugin:  " + ex.Message, Category.Exception, Priority.High );
                throw;
            }
            logger.Log(String.Format("{0} plugins found", result.Count), Category.Info, Priority.Low);
            return result;
        }
    }
    public class PluginLoader : BasePluginLoader {}
}
